using System;
using System.Collections.Generic;
using System.Text;

namespace InfiniTec.Security
{
    /// <summary>
    /// Extends the <see cref="ImpersonationScope"/> for use in console applications by using the
    /// <see cref="CmdLinePromptForCredential"/> class.
    /// </summary>
    public class CmdLineImpersonationScope: CallbackImpersonationScope
    {
        private string _Username;

        /// <summary>
        /// Initializes a new instance of this class.
        /// </summary>
        /// <param name="targetName">The targetname for this request.</param>
        public CmdLineImpersonationScope(string targetName) : this(targetName, "", true) { }
        /// <summary>
        /// Initializes a new instance of this class.
        /// </summary>
        /// <param name="targetName">The targetname for this request.</param>
        /// <param name="impersonateImmediately">True, if impersonation should take place immediately. False, otherwise.</param>
        public CmdLineImpersonationScope(string targetName, bool impersonateImmediately) : this(targetName, "", impersonateImmediately) { }

          /// <summary>
        /// Creates a new instance of this class and impersonates as the user specified by targetName.
        /// </summary>
        /// <param name="targetName">The targetName of the identity, as stored in the <see cref="CredentialManager"/>,</param>
        /// <param name="username">This callback is invoked whenever the username and password are no longer available.</param>
        /// <param name="impersonateImmediately">True, if impersonation should take place immediately. False, otherwise.</param>
        public CmdLineImpersonationScope(string targetName, string username, bool impersonateImmediately)
            : this(targetName, username, LogonType.Interactive, impersonateImmediately) { }

        /// <summary>
        /// Creates a new instance of this class and impersonates as the user specified by targetName.
        /// </summary>
        /// <param name="targetName">The targetName of the identity, as stored in the <see cref="CredentialManager"/>,</param>
        /// <param name="username">This callback is invoked whenever the username and password are no longer available.</param>
        /// <param name="logonType">Specifies the type of logon process.</param>
        /// <param name="impersonateImmediately">True, if impersonation should take place immediately. False, otherwise.</param>
        public CmdLineImpersonationScope(string targetName, string username, LogonType logonType,
            bool impersonateImmediately): base(targetName, null, logonType, false)
        {
            _Username = username;
            CredentialCallback = AcquireCredential;

            if (impersonateImmediately) Impersonate();
        }

        private void AcquireCredential(object source, AcquireCredentialEventArgs e)
        {
            CmdLinePromptForCredential prompt;


            prompt = new CmdLinePromptForCredential(e.TargetName,
                string.IsNullOrEmpty(e.Username) ? _Username : e.Username,
                QueryCredentialOptions.ExcludeCertificates | QueryCredentialOptions.DoNotPersist |
                QueryCredentialOptions.ValidateUsername);
            
            e.Cancel = !prompt.Prompt();
            e.Username = prompt.Username;
            e.Password = prompt.Password;
        }
    }
}
